package com.gitee.wsl.doc.prosemirror.transform.map

// There are several things that positions can be mapped through. Such objects conform to this
// interface.
interface Mappable {
    // Map a position through this object. When given, `assoc` (should be -1 or 1, defaults to 1)
    // determines with which side the position is associated, which determines in which direction
    // to move when a chunk of content is inserted at the mapped position.
    fun map(pos: Int, assoc: Int = 1): Int

    // Map a position, and return an object containing additional information about the mapping. The
    // result's `deleted` field tells you whether the position was deleted (completely enclosed in a
    // replaced range) during the mapping. When content on only one side is deleted, the position
    // itself is only considered deleted when `assoc` points in the direction of the deleted
    // content.
    fun mapResult(pos: Int, assoc: Int = 1): MapResult
}


// An object representing a mapped position with extra information.
class MapResult internal constructor(
    // The mapped version of the position.
    val pos: Int,
    val delInfo: Int,
    val recover: Int?
) {

    // Tells you whether the position was deleted, that is, whether the step removed the token on
    // the side queried (via the `assoc`) argument from the document.
    val deleted: Boolean
        get() = (this.delInfo and DEL_SIDE) > 0

    // Tells you whether the token before the mapped position was deleted.
    val deletedBefore: Boolean
        get() = (this.delInfo and (DEL_BEFORE or DEL_ACROSS)) > 0

    // True when the token after the mapped position was deleted.
    val deletedAfter: Boolean
        get() = (this.delInfo and (DEL_AFTER or DEL_ACROSS)) > 0

    // Tells whether any of the steps mapped through deletes across the position (including both the
    // token before and after the position).
    val deletedAcross: Boolean
        get() = (this.delInfo and DEL_ACROSS) > 0
}